package com.rfid.reader;

import java.io.IOException;

import com.rfid.AppNotifyImpl.GeneralReaderNotifyImpl;

public class GeneralReader extends RfidReader {
	private final static byte START_CMD_FLAG = (byte) 0xA0;
	private final static byte START_RSP_FLAG = (byte)0xE4;
	private final static byte START_NOTIFY_FLAG = (byte)0xE0;

	private final static byte CMD_NOTIFY_TAG = (byte) 0xFF;
	private final static byte RFID_CMD_QUERY_SINGLE_PARAM = 0x61;
	private final static byte RFID_CMD_SET_MUTI_PARAM = 0x62;
	private final static byte RFID_CMD_QUERY_MUTI_PARAM = 0x63;
	private final static byte RFID_CMD_RESET_DEVICE = 0x65;
	private final static byte RFID_CMD_QUERY_VERSION = 0x6A;
	private final static byte RFID_CMD_STOP_INVETORY = (byte) 0xFE;
	private final static byte RFID_CMD_READ_TAG_BLOCK = (byte) 0x80;
	private final static byte RFID_CMD_WRITE_TAG_BLOCK = (byte) 0x81;
	private final static byte RFID_CMD_IDENTIFY_TAG = (byte) 0x82;
	private final static byte RFID_CMD_ENCRYPT_TAG = (byte)0x83;
	private final static byte RFID_CMD_KILL_TAG = (byte) 0x86;
	private final static byte RFID_CMD_LOCK_TAG = (byte) 0x87;


	public final static byte RFID_TAG_MEMBANK_RESERVED = 0;
	public final static byte RFID_TAG_MEMBANK_USER = 3;
	public final static byte RFID_TAG_MEMBANK_EPC = 1;
	public final static byte RFID_TAG_MEMBANK_TID = 2;

	public final static byte RFID_LOCK_USER = 0;
	public final static byte RFID_LOCK_TID = 1;
	public final static byte RFID_LOCK_EPC = 2;
	public final static byte RFID_LOCK_ACCESS_PASSWORD = 3;
	public final static byte RFID_LOCK_KILL_PASSWORD = 4;
	public final static byte RFID_LOCK_ALL = 5;

	public GeneralReader() {
		// TODO Auto-generated constructor stub
		super();
	}

	private void BuildMessageHeader(byte commandCode) {
		// TODO Auto-generated method stub
		sendIndex = 0;
		sendMsgBuff[sendIndex++] = START_CMD_FLAG;
		sendMsgBuff[sendIndex++] = 0;
		sendMsgBuff[sendIndex++] = commandCode;
	}
	
	@Override
	public int Inventory() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int InventoryOnce() throws IOException {
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_IDENTIFY_TAG);
		sendMsgBuff[sendIndex++] = 0x04;
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int Stop() throws IOException {
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_STOP_INVETORY);
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int Reset() throws IOException {
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_RESET_DEVICE);
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int RelayControl(int relayNo, int operation, int time) throws IOException {
		return 0;
	}


	@Override
	public void HandleMessage() {
		// TODO Auto-generated method stub
		byte []message = recvMsgBuff;
		byte checksum = 0;
		byte caculatedChecksum = 0;
		int buffPos = 0;
		int rspLen = 0;
		while (buffPos <= recvMsgLen - 4){
			if ( (message[buffPos] != START_RSP_FLAG) && (message[buffPos] != START_NOTIFY_FLAG))
			{
				buffPos++;
			}
			
			rspLen = getUnsignedByte(message[buffPos+1]);
			checksum = message[buffPos + rspLen + 1];
			caculatedChecksum = CaculateCheckSum(message,buffPos,rspLen+1);
			if (caculatedChecksum == checksum)
			{
				NotifyMessageToApp(message, buffPos);
				buffPos = buffPos + rspLen + 2;
			}
			else {
				++buffPos;
			}
		}
	}

	@Override
	public int HandleRecv() throws IOException {
		// TODO Auto-generated method stub
		recvMsgLen = transport.ReadData(recvMsgBuff);
		HandleMessage();
		return 0;
	}

	private byte CaculateCheckSum(byte []message,int start_pos,int len)
	{
		long checksum = 0;
		int iIndex = 0;
		for (iIndex = 0;iIndex < len; iIndex++)
		{
			checksum += getUnsignedByte(message[start_pos+iIndex]);
		}
		checksum = ~checksum + 1;
		return (byte)(checksum & 0xFF);
	}
	
	@Override
	protected void NotifyMessageToApp(byte[] message, int startIndex) {
		// TODO Auto-generated method stub
		GeneralReaderNotifyImpl appNotify = (GeneralReaderNotifyImpl)getAppNotify();
		if ( null == appNotify) {
			return;
		}
		switch(message[startIndex + 2]) {
		case CMD_NOTIFY_TAG:
			appNotify.NotifyRecvTags(message, startIndex);
			break;
		case RFID_CMD_STOP_INVETORY:
			appNotify.NotifyStopInventory(message, startIndex);
			break;
		case RFID_CMD_RESET_DEVICE:
			appNotify.NotifyReset(message, startIndex);
			break;
		case RFID_CMD_READ_TAG_BLOCK:
			appNotify.NotifyReadTagBlock(message,startIndex);
			break;
		case RFID_CMD_WRITE_TAG_BLOCK:
			appNotify.NotifyWriteTagBlock(message, startIndex);
			break;
		case RFID_CMD_LOCK_TAG:
			appNotify.NotifyLockTag(message, startIndex);
			break;
		case RFID_CMD_KILL_TAG:
			appNotify.NotifyKillTag(message, startIndex);
			break;
		case RFID_CMD_IDENTIFY_TAG:
			appNotify.NotifyInventoryOnce(message, startIndex);
			break;
		case RFID_CMD_QUERY_SINGLE_PARAM:
			appNotify.NotifyQueryMutiParam(message, startIndex);
			break;
		case RFID_CMD_SET_MUTI_PARAM:
			appNotify.NotifySetMutiParam(message, startIndex);
			break;
			default:
				break;
		}
	}

	@Override
	public int ReadTagBlock(byte membank,byte addr,byte len,byte[] accessPassword) throws IOException{
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_READ_TAG_BLOCK);
		sendMsgBuff[sendIndex++] = 0x04;
		sendMsgBuff[sendIndex++] = membank;
		sendMsgBuff[sendIndex++] = addr;
		sendMsgBuff[sendIndex++] = len;
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int WriteTagBlock(byte membank,int addr,byte len, byte[] writtenData,int writeStartIndex,byte[] accessPassword) throws IOException{
		// TODO Auto-generated method stub 
		BuildMessageHeader(RFID_CMD_WRITE_TAG_BLOCK);
		sendMsgBuff[sendIndex++] = 0x04;
		sendMsgBuff[sendIndex++] = 0x01;
		sendMsgBuff[sendIndex++] = membank;
		sendMsgBuff[sendIndex++] = (byte)addr;
		sendMsgBuff[sendIndex++] = len;
		
		//���Ҫд�������
		for (int iIndex = 0; iIndex < len * 2; iIndex++) {
			sendMsgBuff[sendIndex++] = writtenData[writeStartIndex + iIndex];
		}
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int LockTag(byte lockType,byte[] accessPassword) throws IOException{
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_LOCK_TAG);
		sendMsgBuff[sendIndex++] = 0x04;
		sendMsgBuff[sendIndex++] = lockType;
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int KillTag(byte[] accessPassword,byte[] killPassword) throws IOException {
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_KILL_TAG);
		sendMsgBuff[sendIndex++] = 0x04;
		//����Ĭ��ȫΪ0
		sendMsgBuff[sendIndex++] = 0x00;
		sendMsgBuff[sendIndex++] = 0x00;
		sendMsgBuff[sendIndex++] = 0x00;
		sendMsgBuff[sendIndex++] = 0x00;
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	public int QueryParameter(int memAddress, int queryLen) throws IOException{
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_QUERY_MUTI_PARAM);
		sendMsgBuff[sendIndex++] = (byte)queryLen;
		//����Ĭ��ȫΪ0
		sendMsgBuff[sendIndex++] = 0x00;
		sendMsgBuff[sendIndex++] = (byte)memAddress;
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	public int SetMutiParameter(int memAddress, int paramLen, int[] params) throws IOException {
		// TODO Auto-generated method stub
		int paramIndex = 0;
		if (null == params || (paramLen > params.length)) {
			return -1;
		}
		
		BuildMessageHeader(RFID_CMD_SET_MUTI_PARAM);
		sendMsgBuff[sendIndex++] = (byte)paramLen;
		//����Ĭ��ȫΪ0
		sendMsgBuff[sendIndex++] = 0x00;
		sendMsgBuff[sendIndex++] = (byte)memAddress;
		for (paramIndex = 0;paramIndex < paramLen; paramIndex++) {
			sendMsgBuff[sendIndex++] = (byte)params[paramIndex];
		}
		sendMsgBuff[1] = (byte) (sendIndex - 1);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		sendIndex++;
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}


	
}
